/*
 * @(#)DomconGxlOutputCodec.java created 03.02.2006
 * 
 * Copyright (c) 2006 Alexander Koller
 *  
 */

package de.saar.chorus.domgraph.codec.domgraph;

import java.io.IOException;
import java.io.Writer;

import org._3pq.jgrapht.Edge;

import de.saar.basic.XmlEntities;
import de.saar.chorus.domgraph.GlobalDomgraphProperties;
import de.saar.chorus.domgraph.codec.CodecMetadata;
import de.saar.chorus.domgraph.codec.MalformedDomgraphException;
import de.saar.chorus.domgraph.codec.MultiOutputCodec;
import de.saar.chorus.domgraph.graph.DomGraph;
import de.saar.chorus.domgraph.graph.EdgeType;
import de.saar.chorus.domgraph.graph.NodeLabels;
import de.saar.chorus.domgraph.graph.NodeType;

/**
 * An output codec for arbitrary dominance graphs in GXL syntax.
 * For further documentation of this format, see {@link de.saar.chorus.domgraph.codec.domgraph.DomgraphGxlInputCodec}.
 * 
 * @author Alexander Koller
 *
 */
@CodecMetadata(name="domgraph-gxl", extension=".dg.xml")
public class DomgraphGxlOutputCodec extends MultiOutputCodec {
    @Override
	public void encode(DomGraph graph, NodeLabels labels, Writer writer)
            throws IOException, MalformedDomgraphException {
        int count = 0;
        
    	if( !graph.isLabellingConsistent(labels)) {
    		throw new MalformedDomgraphException("Graph labelling information is inconsistent with node labels.");
    	}

        
        writer.write("   <graph id=\"utool-graph\" edgeids=\"true\" hypergraph=\"false\" edgemode=\"directed\">\n");
        
        // iterate over all nodes
        for( String node : graph.getAllNodes() ) {
            writer.write("      <node id=\"" + XmlEntities.encode(node) + "\">\n");
            if( graph.getData(node).getType() == NodeType.LABELLED ) {
                if( graph.outdeg(node) > 0 ) {
                    writer.write("         <type xlink:href=\"root\" />\n");
                } else {
                    writer.write("         <type xlink:href=\"leaf\" />\n");
                }
                
                writer.write("         <attr name=\"label\"><string>"
                        + XmlEntities.encode(labels.getLabel(node))
                        + "</string></attr>\n");
            } else {
                writer.write("         <type xlink:href=\"hole\" />\n");
            }
            writer.write( "      </node>\n");
            
            
            // iterate over edges out of this node
            for( Edge edge : graph.getOutEdges(node, null) ) {
                writer.write("      <edge from=\""
                        + XmlEntities.encode((String) edge.getSource())
                        + "\" to=\"" 
                        + XmlEntities.encode((String) edge.getTarget())
                        + "\" id=\"edge" + (count++) + "\">\n");
                
                if( graph.getData(edge).getType() == EdgeType.TREE ) {
                    writer.write("        <type xlink:href=\"solid\" />\n");
                } else {
                    writer.write("        <type xlink:href=\"dominance\" />\n");
                }
                
                writer.write("      </edge>\n");
            }
            
            writer.write("\n");
        }
        
        writer.write("   </graph>\n");    
        writer.flush();
    }

    @Override
    public void print_header(Writer writer) throws IOException {
        writer.write("<?xml version=\"1.0\"?>\n");
        writer.write("<!-- autogenerated by "
                + GlobalDomgraphProperties.getSystemName()
                + " (see " + GlobalDomgraphProperties.getHomepage()
                + " for details) -->\n\n");
        writer.write("<gxl xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n");
    }

    @Override
    public void print_footer(Writer writer) throws IOException {
        writer.write("</gxl>\n\n");
        writer.flush();
    }

    @Override
    public void print_start_list(Writer writer) throws IOException {
    }

    @Override
    public void print_end_list(Writer writer) throws IOException {
    }

    @Override
    public void print_list_separator(Writer writer) throws IOException {
        writer.write("\n");
    }
    
}
